package com.fm.base.database.domain;

import java.util.Map;

/**
 * @author leo.li
 */
public interface DBDocument extends Map<String, Object> {
    default DBDocument append(String key, Object value) {
        put(key, value);
        return this;
    }

    default Number getNumber(String key) {
        return (Number) get(key);
    }

    default Number getNumber(String key, Number defaultValue) {
        return (Number) getOrDefault(key, defaultValue);
    }

    default String getString(String key) {
        return (String) get(key);
    }

    default String getString(String key, String defaultValue) {
        return (String) getOrDefault(key, defaultValue);
    }

    default DBDocument getDBDocument(String key) {
        return (DBDocument) get(key);
    }

    default DBList getDBList(String key) {
        return (DBList) get(key);
    }

    @SuppressWarnings("unchecked")
    default <O> O getByPath(String path) {
        Object toReturn = this;
        String[] keys = path.split("\\.");
        for (String key : keys) {
            toReturn = ((Map<String, Object>) toReturn).get(key);
            if (toReturn == null) {
                break;
            }
        }
        return (O) toReturn;
    }

    @SuppressWarnings("unchecked")
    default <O> O putByPath(String path, Object value) {
        Map<String, Object> toReturn = this;
        String[] keys = path.split("\\.");
        for (int i = 0; i < keys.length; ++i) {
            toReturn = (Map<String, Object>) toReturn.get(keys[i]);
            if (i == keys.length - 2) {
                if (toReturn.containsKey(keys[keys.length -1])) {
                    return (O) toReturn.put(keys[keys.length - 1], value);
                }
            } else if (toReturn == null) {
                throw new RuntimeException("无效路径:" + path);
            }
        }
        throw new RuntimeException("无效路径:" + path);
    }

    Object put(String key, Object value);

    DBDocument clone();
}
